package com.lecture.junit.tdd.example;

import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import com.lecture.junit.tdd.exceptions.AccountAlreadyLoggedInException;
import com.lecture.junit.tdd.exceptions.AccountIsRevokedException;
import com.lecture.junit.tdd.exceptions.AccountNotUsedException;
import com.lecture.junit.tdd.exceptions.IncorrectNewPasswordException;
import com.lecture.junit.tdd.exceptions.IncorrectPasswordException;
import com.lecture.junit.tdd.exceptions.PasswordExpiredException;

public abstract class LoginServiceState {

    AtomicInteger count;
    AtomicLong timeStamp;
    public void login(LoginServiceInterface context, IAccount acc, String password) {
        if (acc.passwordMatches(password)) {
        	if(isPasswordExpired(acc)) {
        		throw new PasswordExpiredException();
        	}
        	if(isTimeStampElapsed(acc)) {
        		acc.setRevoked();
        		throw new AccountNotUsedException();    		
        	}
            if (acc.isLoggedIn()) {
                throw new AccountAlreadyLoggedInException();
            }
            if (acc.isRevoked()) {
                throw  new AccountIsRevokedException();
            }
            acc.setLoggedIn();
            setTimeStamp();
            context.setState(acc.getUserName(), new AwaitFirstLoginAttempt());
        } else {
            handlePasswordFail(context, acc);
        }
    }
    
    protected abstract void handlePasswordFail(LoginServiceInterface context, IAccount acc);

	public AtomicInteger getCount() {
		return count;
	}
	
	public void setCount(AtomicInteger count) {
		this.count = count;
	}
	
	public void setTimeStamp() {
		this.timeStamp = new AtomicLong(System.currentTimeMillis());
	}
	
    public boolean isPasswordExpired(IAccount acc) {
        Calendar date = Calendar.getInstance();
        date.add(Calendar.DAY_OF_YEAR, -30);
        if (date.after(acc.whenPassChanged())) {
            return true;
        } else {
            return false;
        }
    }
    
    public boolean isTimeStampElapsed(IAccount acc) {
        Calendar date = Calendar.getInstance();
        date.add(Calendar.DAY_OF_YEAR, -45);
        if (date.after(acc.whenLastUsedAccount())) {
            return true;
        } else {
            return false;
        }
    }

	public void changePassword(LoginServiceInterface context, IAccount acc, String oldpass, String newpass) {
		if(!acc.passwordMatches(oldpass)) {
			throw new IncorrectPasswordException();
		} else if(acc.isOldPassword(newpass)) {
			throw new IncorrectNewPasswordException();
		} else {
			acc.setPassword(newpass);
		}
	}
	
}
